package br.indt.framework.scheduler;

/**
 *
 * @author efirmino
 */
class Timer extends Thread {
    private final JobQueue queue;

    public Timer(JobQueue queue) throws NullPointerException {
        if (queue == null) {
            throw new NullPointerException("JobQueue is null");
        }

        this.queue = queue;
    }

    public void run() {
        for(;;) {
            if (queue.isEmpty()) {
                waitQueueChange();
                continue;
            }

            int delta;
            synchronized(queue) {
                delta = queue.getJobTimeStamp(0) - currentTimestamp();
                if (delta <= 0){
                    launchNextTask();
                    continue;
                }
            }

            waitQueueChange(delta);
        }
    }

    private void launchNextTask() {
        Job job = (Job) queue.poll();
        Thread worker = new Thread(job.getTask().getRunnable());
        worker.start();

        if (job.isPeriodic())  {
            queue.add(job);
        }
    }

    private void waitQueueChange() {
        waitQueueChange(0);
    }

    final static int SECOND = 1000;
    private void waitQueueChange(long timeout) {
        try {
            synchronized (this) {
                this.wait(timeout * SECOND);
            }
        } catch (Exception e) {            
        }
    }

    /**
     * Current timestamp in seconds (Overflow in January 19, 2038)
     *
     * @return
     */
    public static int currentTimestamp() {
        return (int) (System.currentTimeMillis() / SECOND);
    }
}
